﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#pragma once

#include "IGraphicsStylePage.h"
#include "Color.h"

#include <map>
#include <list>

#include <QStyledItemDelegate>
#include "UniIdentity.h"

namespace gcmp
{
    class IDocument;
    class IModelView;
    class ICategory;
}

class QTreeView;
class QStandardItemModel;
class QStandardItem;

class LineWidthItemComboxBoxDelegate : public QStyledItemDelegate
{
    Q_OBJECT

public:
    LineWidthItemComboxBoxDelegate(QObject* parent = nullptr);

    // editing
    QWidget *createEditor(QWidget *parent,
        const QStyleOptionViewItem &option,
        const QModelIndex &index) const;

    void setEditorData(QWidget *editor, const QModelIndex &index) const;
    void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const;

    void updateEditorGeometry(QWidget *editor,
        const QStyleOptionViewItem &option,
        const QModelIndex &index) const;

public:
    void SetItems(const std::map<int, QString>& items) { m_items = items; }

private:
    // value to display value
    std::map<int, QString> m_items;
};

class ImportedObjectDocumentStylePage : public QWidget, public IGraphicsStylePage
{
    Q_OBJECT

public:
    struct LineStyleData
    {
        gcmp::UniIdentity CategoryId;

        std::wstring LayerName;
        double LineWidth;
        gcmp::Color LineColor;
        std::wstring LineType;
    };

    struct ImportedObjectStyleData
    {
        std::wstring ObjectName;
        std::list<LineStyleData> LineStyles;
    };

public:
    ImportedObjectDocumentStylePage(QWidget* parent);

    bool InitUI(gcmp::IDocument* pDoc, const std::map<std::wstring, std::list<gcmp::UniIdentity>>& categories);

    // IGraphicsStylePage methods
    QWidget* GetWidgetFW() override;
    std::wstring GetLabel() const override;
    void OnApplied() override;
    virtual void RecordMaterialDatas() override {}

    private slots:
        void OnItemClicked(const QModelIndex& index);
        void OnItemDataChanged(QStandardItem *item);

private:
    bool BuildTreeModel(const std::list<ImportedObjectStyleData>& objectStyles);
    bool SetDelegates();

private:
    QTreeView* m_pTreeView;
    QStandardItemModel* m_pTreeModel;

    gcmp::IDocument* m_pDoc;
};

class ImportedObjectModelViewStylePage : public QWidget, public IGraphicsStylePage
{
    Q_OBJECT

public:
    struct LineStyleData
    {
        gcmp::UniIdentity CategoryId;

        std::wstring LayerName;
        bool Visible;

        double LineWidthInherited;
        double LineWidth; // -1 means no overridden

        gcmp::Color LineColorInherited;
        gcmp::Color LineColor;
        bool LineColorIsOverridden;

        std::wstring LineTypeInherited;
        std::wstring LineType; // empty means no overridden
    };

    struct ImportedObjectStyleData
    {
        std::wstring ObjectName;
        bool ObjectVisible;
        std::list<LineStyleData> LineStyles;
    };

public:
    ImportedObjectModelViewStylePage(QWidget* parent);

    bool InitUI(gcmp::IModelView* pCurrentModelView, const std::map<std::wstring, std::list<gcmp::UniIdentity>>& categories);

    // IGraphicsStylePage methods
    QWidget* GetWidgetFW() override;
    std::wstring GetLabel() const override;
    void OnApplied() override;
    virtual void RecordMaterialDatas() override {}

    private slots:
        void OnItemClicked(const QModelIndex& index);
        void OnItemDataChanged(QStandardItem *item);

private:
    bool BuildTreeModel(const std::list<ImportedObjectStyleData>& objectStyles);
    bool SetDelegates();

    gcmp::IDocument* GetDoc();

private:
    QTreeView* m_pTreeView;
    QStandardItemModel* m_pTreeModel;

    gcmp::IModelView* m_pCurrentModelView;
};

class ImportedObjectStylePageUtils
{
public:
    static bool GetProjectContent(gcmp::IDocument* pDoc, const std::map<std::wstring, std::list<gcmp::UniIdentity>>& categories, std::list<ImportedObjectDocumentStylePage::ImportedObjectStyleData>& objectStyles);
    static bool GetModelViewContent(gcmp::IModelView* pModelView, const std::map<std::wstring, std::list<gcmp::UniIdentity>>& categories, std::list<ImportedObjectModelViewStylePage::ImportedObjectStyleData>& objectStyles);

    static bool GetFamilyNameAndLayerNameFromCategory(
        const gcmp::ICategory* pCategory, 
        std::wstring & familyName,
        std::wstring & layerName
    );
};
